<template>
  <u-form-item
    v-if="element"
    :key="element.model"
    class="generate-item"
    :prop="element.model"
    :label="!element.options.showLabel ? element.fieldName : ''"
    :required="element.options.rules.required"
  >
    <template v-if="element.type !== 'text'" #label>
      {{ !element.options.showLabel ? element.fieldName : '' }}
      <a-tooltip
        v-if="element.options.hidePromptFlag && !element.options.showLabel"
      >
        <template #title>{{ element.options.promptInfo }}</template>
        <Icon class="cursor-pointer" size="20" color="#999"
          ><QuestionCircle16Filled
        /></Icon>
      </a-tooltip>
    </template>
    <template v-if="element.type === 'input'">
      <template v-if="disabled">
        {{ data || '--' }}
      </template>
      <template v-else>
        <view class="white-bg">
          <u-input
            v-model="data"
            :style="{ width: element.options.width }"
            :placeholder="element.options.placeholder"
            :maxlength="parseInt(element.options.maxlength)"
            :clearable="element.options.allowClear"
            :disabled="disabled || element.options.readonlyFlag === 1"
            @change="inputChange"
          />
        </view>
      </template>
    </template>

    <template v-if="element.type === 'password'">
      <u-input
        v-model="data"
        type="password"
        :style="{ width: element.options.width }"
        :placeholder="element.options.placeholder"
        :maxlength="parseInt(element.options.maxlength)"
        :clearable="element.options.allowClear"
        :disabled="disabled || element.options.readonlyFlag === 1"
      />
    </template>

    <template v-if="element.type === 'textarea'">
      <template v-if="disabled">
        {{ data || '--' }}
      </template>
      <template v-else>
        <view class="white-bg">
          <u-input
            v-model="data"
            type="textarea"
            :style="{ width: element.options.width }"
            :placeholder="element.options.placeholder"
            :maxlength="parseInt(element.options.maxlength)"
            :clearable="element.options.allowClear"
            :disabled="disabled || element.options.readonlyFlag === 1"
          />
        </view>
      </template>
    </template>

    <template v-if="element.type === 'number'">
      <template v-if="disabled">
        {{
          element.options.numericFormat == 1
            ? (data || '--') + ''
            : `￥ ${data || '--'}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
        }}
      </template>
      <template v-else>
        <!--TODO：支持货币格式，支持小数点-->
        <!-- <a-input-number
          v-model:value="data"
          :size="config.size"
          :style="{ width: element.options.width }"
          :controls="false"
          decimal-separator="2"
          :disabled="disabled || element.options.readonlyFlag === 1"
          :placeholder="element.options.placeholder"
          :formatter="
            (value) =>
              element.options.numericFormat == 1
                ? value + ''
                : `￥ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
          "
          :parser="
            (value) =>
              element.options.numericFormat == 1
                ? value
                : value.replace(/\￥\s?|(,*)/g, '')
          "
          @change="numberChange"
        /> -->
        <u-input
          v-model="data"
          type="number"
          :style="{ width: element.options.width }"
          :placeholder="element.options.placeholder"
          :maxlength="parseInt(element.options.maxlength)"
          :clearable="element.options.allowClear"
          :disabled="disabled || element.options.readonlyFlag === 1"
        />
      </template>
    </template>

    <template v-if="element.type === 'radio'">
      <template v-if="disabled">
        {{ element.options.valueContextObj.optionVal?.label || '--' }}
      </template>
      <template v-else>
        <u-radio-group
          v-model="data"
          :style="{ width: element.options.width }"
          :disabled="disabled || element.options.readonlyFlag === 1"
          @change="radioOptionChange"
        >
          <u-radio
            v-for="item of element.options.remote === 2
              ? element.options.remoteOptions
              : element.options.options"
            :key="item.value"
            :name="item.value"
            :style="{
              display: element.options.inline ? 'inline-block' : 'block',
            }"
            >{{ item.label }}</u-radio
          >
        </u-radio-group>
      </template>
    </template>

    <template v-if="element.type === 'checkbox'">
      <template v-if="disabled">
        {{
          element.options.valueContextObj.optionsVal
            ? element.options.valueContextObj.optionsVal
                .map((item: any) => item.fullLabel || item.label)
                .join('、')
            : '--'
        }}
      </template>
      <template v-else>
        <u-checkbox-group
          v-model="data"
          :style="{ width: element.options.width }"
          :disabled="disabled || element.options.readonlyFlag === 1"
        >
          <u-checkbox
            v-for="item of element.options.remote === 2
              ? element.options.remoteOptions
              : element.options.options"
            :key="item.value"
            :name="item.value"
            :style="{
              display: element.options.inline ? '' : 'block',
            }"
            >{{ item.label }}</u-checkbox
          >
        </u-checkbox-group>
      </template>
    </template>

    <template v-if="element.type === 'time'">
      <!--暂无使用-->
      <a-time-picker
        v-model:value="data"
        :size="config.size"
        :placeholder="element.options.placeholder"
        :input-read-only="element.options.readonlyFlag === 1"
        :allow-clear="element.options.allowClear"
        :format="element.options.format"
        :value-format="element.options.valueFormat"
        :disabled="disabled || element.options.readonlyFlag === 1"
        :style="{ width: element.options.width }"
      />
    </template>

    <template v-if="element.type === 'date'">
      <template v-if="disabled">
        {{ element.options.valueContextObj?.stringVal || '--' }}
      </template>
      <template v-else>
        <view class="white-bg">
          <datePicker
            v-model="data"
            :placeholder="element.options.placeholder"
            :option="element.options"
          ></datePicker>
        </view>
      </template>
    </template>

    <template v-if="element.type === 'rate'">
      <a-rate
        v-model:value="data"
        :count="element.options.max"
        :allow-half="element.options.allowHalf"
        :allow-clear="element.options.allowClear"
        :disabled="disabled || element.options.disabled"
      />
    </template>

    <template v-if="element.type === 'select'">
      <template v-if="element.options.multipleFlag">
        <template v-if="disabled">
          {{
            element.options.valueContextObj.optionsVal
              ? element.options.valueContextObj.optionsVal
                  .map((item: any) => item.fullLabel || item.label)
                  .join('、')
              : '--'
          }}
        </template>
        <template v-else>
          <a-select
            v-model:value="data"
            :size="config.size"
            mode="multiple"
            :placeholder="element.options.placeholder"
            :filter-option="handleFilterOption"
            :allow-clear="element.options.clearable"
            :disabled="disabled || element.options.readonlyFlag === 1"
            :style="{ width: element.options.width }"
            :not-found-content="element.options.notFoundContent"
            @change="selectOptionChange"
          >
            <template v-if="element.options.remote === 2">
              <a-select-option
                v-for="item of element.options.remoteOptions"
                :key="item.value"
                :value="item.value"
                :label="item.fullLabel"
              >
                {{ item.fullLabel }}
              </a-select-option>
            </template>
            <template v-else>
              <a-select-option
                v-for="item of element.options.options"
                :key="item.value"
                :value="item.value"
                :label="item.label"
              >
                {{ item.label }}
              </a-select-option>
            </template>
          </a-select>
        </template>
      </template>
      <template v-else>
        <template v-if="disabled">
          {{
            element.options.valueContextObj?.optionsVal?.[0].fullLabel ||
            element.options.valueContextObj?.optionsVal?.[0].label ||
            '--'
          }}
        </template>
        <template v-else>
          <a-select
            v-model:value="data"
            :size="config.size"
            :placeholder="element.options.placeholder"
            :filter-option="
              element.options.remote === 2 ? false : handleFilterOption
            "
            :allow-clear="element.options.clearable"
            show-search
            :disabled="disabled || element.options.readonlyFlag === 1"
            :style="{ width: element.options.width }"
            :not-found-content="element.options.notFoundContent"
            @search="handleSearch"
            @change="selectOptionChange"
          >
            <template v-if="element.options.remote === 2">
              <a-select-option
                v-for="item of element.options.remoteOptions"
                :key="item.value"
                :value="item.value"
                :label="item.fullLabel"
              >
                {{ item.fullLabel }}
              </a-select-option>
            </template>
            <template v-else>
              <a-select-option
                v-for="item of element.options.options"
                :key="item.value"
                :value="item.value"
                :label="item.label"
              >
                {{ item.label }}
              </a-select-option>
            </template>
          </a-select>
        </template>
      </template>
    </template>

    <template v-if="element.type === 'switch'">
      <a-switch
        v-model:checked="data"
        :size="config.size === 'large' ? 'default' : config.size"
        :checked-children="element.options.checkedChildren"
        :un-checked-children="element.options.unCheckedChildren"
        :disabled="disabled || element.options.disabled"
      />
    </template>

    <template v-if="element.type === 'slider'">
      <a-slider
        v-model:value="data"
        :min="element.options.min"
        :max="element.options.max"
        :step="element.options.step"
        :range="element.options.range"
        :reverse="element.options.reverse"
        :disabled="disabled || element.options.disabled"
        :style="{ width: element.options.width }"
      />
    </template>

    <template v-if="element.type === 'text'">
      <h1>
        <span v-if="!element.options.showLabel">{{ element.fieldName }}</span>
        <a-tooltip v-if="element.options.hidePromptFlag">
          <template #title>{{ element.options.promptInfo }}</template>
          <!-- <Icon class="cursor-pointer" size="20" color="#999"
            ><QuestionCircle16Filled
          /></Icon> -->
          <u-icon name="question-circle-fill" color="#999" size="20"></u-icon>
        </a-tooltip>
      </h1>
      <span v-if="!element.options.hidePromptFlag" class="filed-desc">{{
        element.options.promptInfo
      }}</span>
      <a-divider v-if="element.options.showDivider" style="margin: 0" />
    </template>

    <template v-if="element.type === 'upload'">
      <!-- <UploadFile
        v-model:fileList="data"
        :limit="element.options.attachmentNumber"
        :readonly="disabled || element.options.disabled"
        :show-file-list="true"
      /> -->
      <updateFileVue v-model="data"></updateFileVue>
    </template>

    <template v-if="element.type === 'img-upload'">
      <a-upload
        :name="element.options.file"
        :action="element.options.action"
        :accept="element.options.accept"
        :file-list="data"
        :list-type="element.options.listType"
        :multiple="element.options.multiple"
        :disabled="disabled || element.options.disabled"
        @change="handleUploadChange"
      >
        <SvgIcon
          v-if="element.options.listType === 'picture-card'"
          name="insert"
          prefix="icon-form"
        />
        <a-button v-else>
          <SvgIcon
            name="img-upload"
            prefix="icon-form"
            style="margin-right: 10px"
          />
          点击上传
        </a-button>
      </a-upload>
    </template>

    <template v-if="element.type === 'richtext-editor'">
      <!-- <RichTextEditor
        v-model:value="data"
        :disable="disabled || element.options.disabled"
        :style="{ width: element.options.width }"
      /> -->
    </template>

    <template v-if="element.type === 'cascader'">
      <a-cascader
        v-model:value="data"
        :size="config.size"
        :options="element.options.remoteOptions"
        :placeholder="element.options.placeholder"
        :allow-clear="element.options.allowClear"
        :disabled="disabled || element.options.readonlyFlag === 1"
        expand-trigger="hover"
        :style="{ width: element.options.width }"
        @change="changeCascaderOption"
      />
    </template>
    <p
      v-if="element.type !== 'text' && !element.options.hidePromptFlag"
      class="filed-desc"
    >
      {{ element.options.promptInfo }}
    </p>
  </u-form-item>
</template>

<script lang="ts">
import { computed, defineComponent, PropType, ref } from 'vue';
// import SvgIcon from '@/components/SvgIcon.vue'
// import RichTextEditor from '@/components/RichTextEditor.vue'
import { WidgetForm } from './config/antd';
// import { QuestionCircle16Filled } from '@vicons/fluent';
// import { http } from '@/utils/axios/init';
import { http } from '@/api/service';
import {
  getDatePickerType,
  getDatePickerFormat,
  getDatePickerShowTime,
  getValueByModel,
} from './config';
import { debounce } from 'lodash-es';
import datePicker from './components/datePicker.vue';
import updateFileVue from '@/components/updateFile.vue';

export default defineComponent({
  name: 'AntdGenerateFormItem',
  components: {
    // QuestionCircle16Filled,
    // SvgIcon,
    // RichTextEditor
    datePicker,
    updateFileVue,
  },
  props: {
    config: {
      type: Object as PropType<WidgetForm['config']>,
      required: true,
    },
    element: {
      type: Object,
      required: true,
    },
    model: {
      type: Object,
      required: true,
    },
    disabled: {
      type: Boolean,
      required: true,
    },
    remoteReplace: {
      type: Object,
      required: true,
    },
  },
  emits: {
    change: null,
  },
  setup(props, context) {
    console.log(props.element.options.rules.required);
    const data = computed({
      get: () =>
        getValueByModel(props.model[props.element.model], props.element),
      set: (val: any) => {
        if (props.element.type !== 'select') {
          // eslint-disable-next-line vue/no-mutating-props
          props.model[props.element.model] = val;
          return;
        }
        if (props.element.options.multipleFlag) {
          const optionArr =
            props.element.options.remote === 1
              ? props.element.options.options
              : props.element.options.remoteOptions;
          const tempArr: any = [];
          for (const optVal of val) {
            const option = optionArr.find((opt: any) => opt.value === optVal);
            if (option) {
              tempArr.push({
                value: option.value,
                label: option.label,
                fullLabel: option.fullLabel,
              });
            }
          }
          // eslint-disable-next-line vue/no-mutating-props
          props.model[props.element.model] = tempArr;
        } else {
          const optionArr =
            props.element.options.remote === 1
              ? props.element.options.options
              : props.element.options.remoteOptions;
          const tempObj: any = {};
          const option = optionArr.find((opt: any) => opt.value === val);
          if (option) {
            tempObj.value = option.value;
            tempObj.label = option.label;
            tempObj.fullLabel = option.fullLabel;
          }
          // eslint-disable-next-line vue/no-mutating-props
          props.model[props.element.model] = tempObj;
        }
      },
    });

    const handleFilterOption = (input: string, option: { label: string }) =>
      option.label.toLowerCase().includes(input);

    const handleUploadChange = ({ fileList }: any) => {
      // 文件上传组件未对接
      data.value = fileList;
    };

    /**
     * 选中选项的展示值（单选）
     */
    const selectedLabel = ref('');

    const setLabelAndUpdateOpt = (val?: any) => {
      const item = props.element;
      if (item.options.remote !== 2) {
        // 非远端数据源
        return;
      }
      if (val === undefined || val === null || val === '') {
        // 未输入搜索时，优先从读取选中选项的label
        selectedLabel.value = props.model[props.element.model]?.label || '';
      } else {
        selectedLabel.value = val;
      }
      getRemoteData();
    };

    setLabelAndUpdateOpt();

    // 远端搜索
    const handleSearch = debounce((val: any) => {
      setLabelAndUpdateOpt(val);
    }, 500);

    /**
     * 查询远端数据
     */
    function getRemoteData() {
      if (props.disabled) {
        // 表单整体只读，不需要查询数据
        return;
      }
      const item = props.element;
      if (item.options.remote !== 2) {
        // 非远端数据源
        return;
      }
      if (!item.options.remoteConfig.url) {
        // 未配置远端请求地址
        item.options.remoteOptions = [];
        return;
      }
      if (
        !props.remoteReplace.projectId &&
        item.options.remoteConfig.url.includes('${projectId}')
      ) {
        // 未指明项目Id且未在项目中预览，无法获取项目Id
        item.options.remoteOptions = [];
        item.options.notFoundContent =
          '预览时暂无数据，请在具体项目中使用时进行选择';
        return;
      }
      const url = item.options.remoteConfig.url
        .replace(/\$\{orgId\}/, props.remoteReplace.orgId || -1)
        .replace(/\$\{projectId\}/, props.remoteReplace.projectId || 0)
        .replace(/\$\{searchVal\}/, selectedLabel.value);
      http
        .middleware({
          url: url,
          method: 'GET',
        })
        .then((json: any) => {
          if (item.type === 'cascader') {
            item.options.remoteOptions = json.map((data: any) => ({
              label: data[item.options.remoteConfig.labelKey],
              value: data[item.options.remoteConfig.valueKey],
              children: data[item.options.remoteConfig.children],
            }));
            return;
          }
          if (item.options.multipleFlag) {
            item.options.remoteOptions = convertSelectRemoteOptions(json);
            return;
          }
          if (json.list && json.list instanceof Array) {
            item.options.remoteOptions = convertSelectRemoteOptions(json.list);
          }
        });
    }

    /**
     * 转换选择框的远端选项
     */
    const convertSelectRemoteOptions = (remoteArr: any) => {
      const remoteConfig = props.element.options.remoteConfig;
      const labelStr = remoteConfig.fullLabel;
      if (labelStr) {
        const keyArr = parseLableKey(labelStr);
        const arr: any[] = [];
        for (const tempItem of remoteArr) {
          let fullLabel = labelStr;
          for (const key of keyArr) {
            fullLabel = fullLabel.replace(
              '${' + key + '}',
              tempItem[key] || ''
            );
          }
          arr.push({
            label: tempItem[remoteConfig.labelKey],
            value: tempItem[remoteConfig.valueKey],
            fullLabel,
          });
        }
        return arr;
      }
      return remoteArr.map((data: any) => ({
        label: data[remoteConfig.labelKey],
        value: data[remoteConfig.valueKey],
        fullLabel: data[remoteConfig.labelKey],
      }));
    };

    /**
     * 解析远端配置中的标签
     */
    const parseLableKey = (str: string) => {
      const reg = /\$\{(\w*)\}/g;
      let temp: any = [];
      const keyArr: any[] = [];
      while ((temp = reg.exec(str))) {
        keyArr.push(temp[1]);
      }
      return keyArr;
    };

    const radioOptionChange = () => {
      context.emit('change', { element: props.element, value: data.value });
    };

    const selectOptionChange = (val: any) => {
      if (!props.element.options.multipleFlag) {
        setLabelAndUpdateOpt();
      }
      context.emit('change', { element: props.element, value: val });
    };

    const changeCascaderOption = (value: any) => {
      context.emit('change', { element: props.element, value });
    };

    const inputChange = () => {
      context.emit('change', {
        element: props.element,
        value: getValueByModel(props.model[props.element.model], props.element),
      });
    };

    const numberChange = (value: number | string) => {
      context.emit('change', { element: props.element, value });
    };

    return {
      data,
      handleFilterOption,
      handleUploadChange,
      radioOptionChange,
      selectOptionChange,
      handleSearch,
      getDatePickerType,
      getDatePickerFormat,
      getDatePickerShowTime,
      changeCascaderOption,
      inputChange,
      numberChange,
    };
  },
});
</script>
<style lang="scss" scoped>
.generate-item {
  h1 {
    font-size: 16px;
    font-weight: bold;
  }
  .white-bg {
    background-color: #fff;
    border-radius: 16rpx;
    padding: 0 20rpx;
  }
  .filed-desc {
    font-size: 24rpx;
    line-height: 35rpx;
    color: $u-type-info;
  }
}
</style>
